package com.hyzx.qbasic.admin.domain.service.impl;

import com.github.pagehelper.PageInfo;
import com.hyzx.qbasic.admin.model.constant.CacheKeyConst;
import com.hyzx.qbasic.admin.model.dto.AdminUserInfo;
import com.hyzx.qbasic.admin.model.dto.AdminUserToken;
import com.hyzx.qbasic.admin.model.enums.UserStatus;
import com.hyzx.qbasic.admin.model.po.AdminUserInfoPO;
import com.hyzx.qbasic.admin.model.po.AdminUserPO;
import com.hyzx.qbasic.admin.model.po.AdminUserTokenPO;
import com.hyzx.qbasic.admin.model.vo.req.admin.*;
import com.hyzx.qbasic.admin.model.vo.res.BaseOperationRes;
import com.hyzx.qbasic.admin.common.util.OperationResUtils;
import com.hyzx.qbasic.admin.common.util.PasswordEncryptor;
import com.hyzx.qbasic.common.util.UuidUtils;
import com.hyzx.qbasic.admin.domain.repository.IAdminUserRepository;
import com.hyzx.qbasic.admin.domain.repository.IResourceRepository;
import com.hyzx.qbasic.admin.domain.service.IAdminUserService;
import com.hyzx.qbasic.admin.domain.service.IRoleService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * Created by 黄江华 on 2017/9/21
 */

@Service
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) //使用缓存需加此注解
public class AdminUserServiceImpl implements IAdminUserService {

    @Autowired
    private IAdminUserRepository userRepository;

    @Autowired
    private IRoleService roleService;

    @Autowired
    private IResourceRepository resourceRepository;

    /**
     * 获取用户令牌信息，包含用户密码信息
     */
    @Override
    @Cacheable(cacheNames = CacheKeyConst.ADMIN_USER_TOKEN_CACHE_NAME, key = "#userName")
    public AdminUserToken getUserToken(String userName) {
        AdminUserTokenPO adminUserTokenPO = userRepository.getUserToken(userName);

        if (adminUserTokenPO == null)
            return null;

        AdminUserToken adminUserToken = new AdminUserToken();
        adminUserToken.setUserStatus(UserStatus.values()[adminUserTokenPO.getUserStatus()]);
        BeanUtils.copyProperties(adminUserTokenPO, adminUserToken, "userStatus");

        return adminUserToken;
    }

    /**
     * 获取用户信息，不包含密码信息
     */
    @Override
    public AdminUserInfo getUserInfo(int userId) {
        AdminUserInfoPO adminUserInfoPO = userRepository.getUserInfoById(userId);
        if (adminUserInfoPO == null)
            return null;

        AdminUserInfo adminUserInfo = new AdminUserInfo();
        BeanUtils.copyProperties(adminUserInfoPO, adminUserInfo);

        return adminUserInfo;
    }

    @Override
    public AdminUserPO getFullUserInfo(String userName) {
        return userRepository.getFullUserInfo(userName);
    }

    @Override
    public PageInfo<AdminUserInfoPO> getPagedUserList(GetUserListReq req) {
        PageInfo<AdminUserInfoPO> userList = userRepository.getPagedUserList(req.getPageNum(),
                req.getPageSize(), req.getUserName(), req.getRoleId());

        return userList;
    }

    @Override
    public BaseOperationRes addUser(AddUserReq req) {
        //检查用户名是否已存在
        AdminUserInfoPO existedUser = userRepository.getUserInfoByName(req.getUserName());
        if (existedUser != null)
            return OperationResUtils.fail("用户名已存在");

        String salt = UuidUtils.getObjectId();
        String fullSalt = req.getUserName() + salt;
        String password = PasswordEncryptor.encrypt(req.getPassword(), fullSalt);

        AdminUserPO newUser = new AdminUserPO();
        newUser.setUserName(req.getUserName());
        newUser.setPassword(password);
        newUser.setSalt(salt);
        newUser.setRealName(req.getRealName());
        newUser.setUserStatus(req.getUserStatus());
        newUser.setCreateTime(new Date());
        newUser.setUpdateTime(new Date());

        List<Integer> roleList = new ArrayList<>(req.getUserRoleList().size());
        roleService.getAllRoleList().forEach(role -> {
            req.getUserRoleList().forEach(roleName -> {
                if (role.getRoleName().equals(roleName))
                    roleList.add(role.getRoleId());
            });
        });

        Integer orgId = null;
        if (!CollectionUtils.isEmpty(req.getOrgIdList()))
            orgId = req.getOrgIdList().get(req.getOrgIdList().size() - 1);

        boolean success = userRepository.addUser(newUser, roleList, orgId);
        if (!success)
            return OperationResUtils.fail("新增用户失败");

        return OperationResUtils.success();
    }

    @Override
    @CacheEvict(cacheNames = CacheKeyConst.ADMIN_USER_TOKEN_CACHE_NAME, allEntries = true)
    public BaseOperationRes deleteUser(DeleteUserReq req) {
        boolean success = userRepository.deleteUser(req.getUserIdList());
        if (!success)
            return OperationResUtils.fail("删除用户失败");

        return OperationResUtils.success();
    }

    @Override
    @CacheEvict(cacheNames = CacheKeyConst.ADMIN_USER_TOKEN_CACHE_NAME, key = "#req.userName")
    public BaseOperationRes editUser(EditUserReq req) {
        //检查用户是否存在
        AdminUserInfoPO existedUser = userRepository.getUserInfoById(req.getUserId());
        if (existedUser == null)
            return OperationResUtils.fail("用户不存在");

        AdminUserPO adminUserPO = new AdminUserPO();
        adminUserPO.setUserId(existedUser.getUserId());
        adminUserPO.setUserName(existedUser.getUserName());
        adminUserPO.setRealName(req.getRealName());
        adminUserPO.setUserStatus(req.getUserStatus());
        adminUserPO.setUpdateTime(new Date());

        List<Integer> roleList = new ArrayList<>(req.getUserRoleList().size());
        roleService.getAllRoleList().forEach(role -> {
            req.getUserRoleList().forEach(roleName -> {
                if (role.getRoleName().equals(roleName))
                    roleList.add(role.getRoleId());
            });
        });

        Integer orgId = null;
        if (!CollectionUtils.isEmpty(req.getOrgIdList()))
            orgId = req.getOrgIdList().get(req.getOrgIdList().size() - 1);

        boolean success = userRepository.editUser(adminUserPO, roleList, orgId);
        if (!success)
            return OperationResUtils.fail("编辑用户信息失败");

        return OperationResUtils.success();
    }

    @Override
    @CacheEvict(cacheNames = CacheKeyConst.ADMIN_USER_TOKEN_CACHE_NAME, key = "#req.userName")
    public BaseOperationRes resetPass(ResetPassReq req) {
        if (!req.getPassword().equals(req.getPassword2()))
            return OperationResUtils.fail("两次输入的密码不一致");

        //检查用户是否存在
        AdminUserInfoPO existedUser = userRepository.getUserInfoById(req.getUserId());
        if (existedUser == null)
            return OperationResUtils.fail("用户不存在");

        String salt = UuidUtils.getObjectId();
        String fullSalt = existedUser.getUserName() + salt;
        String password = PasswordEncryptor.encrypt(req.getPassword(), fullSalt);

        AdminUserPO adminUserPO = new AdminUserPO();
        adminUserPO.setUserId(existedUser.getUserId());
        adminUserPO.setUserName(existedUser.getUserName());
        adminUserPO.setPassword(password);
        adminUserPO.setSalt(salt);
        adminUserPO.setUpdateTime(new Date());

        boolean success = userRepository.resetPass(adminUserPO);
        if (!success)
            return OperationResUtils.fail("重置用户密码失败");

        return OperationResUtils.success();
    }

    @Override
    @CacheEvict(cacheNames = CacheKeyConst.ADMIN_USER_TOKEN_CACHE_NAME, key = "#req.userName")
    public BaseOperationRes changePass(ChangePassReq req) {
        if (!req.getPassword().equals(req.getPassword2()))
            return OperationResUtils.fail("两次输入的密码不一致");

        //校验用户是否存在
        String userName = req.getUserName();
        AdminUserToken adminUserToken = getUserToken(userName);
        if (adminUserToken == null)
            return OperationResUtils.fail("用户不存在");

        //检查密码是否匹配
        String oldSalt = userName + adminUserToken.getSalt();
        String encryptedPassword = PasswordEncryptor.encrypt(req.getOldPass(), oldSalt);

        if (!adminUserToken.getPassword().equals(encryptedPassword))
            return OperationResUtils.fail("原密码不正确");

        String salt = UuidUtils.getObjectId();
        String fullSalt = adminUserToken.getUserName() + salt;
        String password = PasswordEncryptor.encrypt(req.getPassword(), fullSalt);

        AdminUserPO adminUserPO = new AdminUserPO();
        adminUserPO.setUserId(adminUserToken.getUserId());
        adminUserPO.setUserName(adminUserToken.getUserName());
        adminUserPO.setPassword(password);
        adminUserPO.setSalt(salt);
        adminUserPO.setUpdateTime(new Date());

        boolean success = userRepository.resetPass(adminUserPO);
        if (!success)
            return OperationResUtils.fail("修改密码失败");

        return OperationResUtils.success();
    }

    @Override
    public List<AdminUserInfoPO> getPermittedUserList(String permission) {
        List<Integer> roleIdList = resourceRepository.getResourceRoles(permission);
        if (CollectionUtils.isNotEmpty(roleIdList)) {
            return userRepository.getUserListByRole(roleIdList);
        }

        return Collections.EMPTY_LIST;
    }

    @Override
    public List<AdminUserInfoPO> getMultiUserInfo(List<Integer> userIdList) {
        return userRepository.getMultiUserInfo(userIdList);
    }
}